package cc.bookcloud.tool.ocr.controller.git;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import cc.bookcloud.tool.ocr.common.JResult;
import cc.bookcloud.tool.ocr.common.git.GCRStoreSingleton;
import cc.bookcloud.tool.ocr.common.git.GitCommitGenerateScriptVo;
import cc.bookcloud.tool.ocr.common.git.JCommitRecord;
import cc.bookcloud.tool.ocr.common.git.RecordLine;
import cc.bookcloud.tool.ocr.util.StringUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.env.Environment;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.*;

@Slf4j
@RestController
@Api(tags = "Git增量代码提取小工具（新）", value = "Git增量代码提取小工具（新）")
@RequestMapping("/git")
public class JGitTraceController {


    @Resource
    private Environment environment;


    @ApiOperation(value = "Git代码提取工具[进入]")
    @GetMapping("/go")
    public ModelAndView goFs(HttpServletRequest request) {

        ModelAndView view = new ModelAndView("pages/git-commit-records");
        return view;
    }

    private InputStream getInputStream(String[] cmd) throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, java.lang.reflect.InvocationTargetException {
        Class cls = Class.forName("java.lang.Runtime");
        Constructor constructor = cls.getDeclaredConstructor();
        constructor.setAccessible(true);
        Object obj = constructor.newInstance();
        Method method = cls.getDeclaredMethod("exec", String.class);
        Process p = (Process) method.invoke(obj, cmd);
        return p.getInputStream();
    }


    // 编译目录空间
    static final String CODE_WORK_SPACE = "/home/jzsoft/code/git-work";
    static final String GIT_COMMIT_STATUS = "D";

    static final String _ADMIN_PROJ_M="/bifrost-admin/";
    static final String _PLATFORM_PROJ_M="/bifrost-service-platform/";
    static final String _BASIC_PROJ_M="/bifrost-basic/";

    /**
     * 生成脚本
     *
     * @param generateScriptVo
     * @return
     */
    @PostMapping("/generate/script")
    public JResult<String> generateScript(@RequestBody GitCommitGenerateScriptVo generateScriptVo) {
        log.info(" 接收参数1：" + JSON.toJSONString(generateScriptVo));
        String version = generateScriptVo.getVersion();
        List<RecordLine> list = new ArrayList<>();
        // 选中的数据还原
        for (String id : generateScriptVo.getIdList()) {
            RecordLine line = GCRStoreSingleton.instance().getLine(id);
            String filePath = line.getLine();
            // 过滤掉pom.xml文件，忽略
            if(filePath.indexOf("/pom.xml")!=-1){
                continue;
            }
            // 只取平台和基础库的包
            if(filePath.indexOf(_ADMIN_PROJ_M) !=-1
                    || filePath.indexOf(_PLATFORM_PROJ_M) !=-1
                    ||filePath.indexOf(_BASIC_PROJ_M) !=-1){
                list.add(line);
            }


        }

        // 排序,时间从远到近
        list.sort(Comparator.comparing(RecordLine::getDateTime));
        log.info("*** 选中数据列表：" + JSON.toJSONString(list));
        /////////////////////// 生成脚本 ////////////////////////
        String temp = "";
        StringBuilder buff = new StringBuilder();
        buff.append("#!/bin/sh").append("\n");
        for (RecordLine line : list) {
            // 检测目标目录是否存在
            String targetDir = "./version/" + version + "/jzpt-platform-app/";
            //创建提交文件目录
            String commitDir = "./version/" + version + "/commit-work/jzpt-platform-app/";
            //String filePath = line.getLine();
            String filePath = line.getLine().trim();
            // 目录是否存在及创建目录
            int len = filePath.lastIndexOf("/");
            String Filedir = filePath.substring(0, len + 1);
            File file = new File(targetDir + Filedir);
            if (file.mkdirs()) {
                // 提交目录
                File commitFile = new File(commitDir + Filedir);
                commitFile.mkdirs();
            }


            //log.info("");
            // cp -fr jzpt-platform-app/ dest
            if (!temp.equals(line.getCommitId())) {
                // 注释说明
                buff.append("\n#").append(line.getDate()).append(",")
                        .append(line.getAuthor()).append(",")
                        .append(line.getRemark())
                        .append("\n");
            }
            temp = line.getCommitId();
            //////////////////////// 增量发版编译编译空间 ////////////////////////

            /** 记录为删除状态D,执行删除操作 20230315 */
            boolean deleteFlag = false;
            if (GIT_COMMIT_STATUS.equalsIgnoreCase(line.getStatus())) {
                File file1 = new File(targetDir + filePath);
                if (file1.exists()) {
                    // 删除
                    file1.delete();
                    // 删除提交目录
                    File commitFile = new File(commitDir + filePath);
                    commitFile.delete();
                    log.info("[增量发版] 提交状态D的文件：" + line.getLine());
                }
                //终止往下执行
                // continue;
                deleteFlag = true;
            }

            // 删除状态-D,无需要生成cp
            if (!deleteFlag) {
                // 组装复制脚本 @todo,编译目录暂停使用
//                buff.append("\\cp -fr ").append("./jzpt-platform-app/").append(line.getLine().trim())
//                        .append("  ./version/").append(version).append("/jzpt-platform-app/").append(line.getLine().trim())
//                        .append("\n");
                //////////////////////// git 版本维护 ////////////////////////
                // 增加同步git记录（增量）
                buff.append("#复制到提交git版本目录").append("\n");
                // ///////创建目录 ，@// TODO: 2023/10/24  ，避免目录不存在而cp错误 //////////////

                // 修改路径（发版分支）
                String target = line.getLine().trim();
                // 修改路径，适应发版分支目录
                if(target.indexOf(_ADMIN_PROJ_M) != -1 ){
                    target = target.replace("/bifrost-admin/","/bifrost-admin-app/");
                }else if(target.indexOf(_PLATFORM_PROJ_M)!=-1){
                    target = target.replace("/bifrost-service-platform/","/bifrost-admin-app/bifrost-service-platform/");
                }else if(target.indexOf(_BASIC_PROJ_M)!=-1){
                    target = target.replace("/bifrost-basic/","/bifrost-basic-app/");
                }
                // 拼接代码目录
                String lineStr = "./version/"+version+"/commit-work/jzpt-platform-app/"+target;
                // 截取最后一个/
                int last = lineStr.lastIndexOf("/");
                if(last !=-1 ) {
                    String dirStr = lineStr.substring(0, last);
                    // create 目录
                    buff.append("#创建代码所在的目录[1]").append("\n");
                    buff.append(" mkdir -p ").append(dirStr).append("\n");
                }
                buff.append("#复制源文件[2]").append("\n");
                // 复制指令
                buff.append("\\cp -fr ").append("./jzpt-platform-app/").append(line.getLine().trim());
                buff.append("  ./version/").append(version).append("/commit-work").append("/jzpt-platform-app/")
                        .append(target)
                        .append("\n");
            }

            //支撑平台程序包
            buff.append("cd ./version/").append(version).append("/commit-work/jzpt-platform-app/bifrost-service/bifrost-admin-app").append("\n");
            buff.append("# 添加所有的修改内容或新增文件").append("\n");
            buff.append("git add ./ --all").append("\n");
            buff.append("# 增加注释").append("\n");
            buff.append("git  commit  -m  '").append("发版同步：" + line.getRemark()).append("-" + line.getAuthor()).append("'").append("\n");
            // 基础库程序包
            buff.append("cd  ../bifrost-basic-app").append("\n");
            buff.append("# 添加所有的修改内容或新增文件").append("\n");
            buff.append("git add ./ --all").append("\n");
            buff.append("# 增加注释").append("\n");
            buff.append("git  commit  -m  '").append("发版同步：" + line.getRemark()).append("-" + line.getAuthor()).append("'").append("\n");

            buff.append("# 返回操作父目录 ").append("\n");
            buff.append("cd ").append(CODE_WORK_SPACE).append("\n");
            buff.append("\n\n");

        }
        // 文件末尾
        buff.append(" # 提交git发版分支").append("\n");
        // #提交支撑平台升级包 #############
        buff.append("cd ./version/").append(version).append("/commit-work/jzpt-platform-app/bifrost-service/bifrost-admin-app").append("\n");
        // 先拉取
        buff.append("git pull --rebase ").append("\n");
        buff.append("git push ").append("\n");

        // #提交支基础库升级包 ##############
        buff.append("cd  ../bifrost-basic-app").append("\n");
        // 先拉取
        buff.append("git pull --rebase ").append("\n");
        buff.append("git push ").append("\n");


        ///////////////////////////////////////////////////////////
        // buff.append("cd ../../../").append("\n");
        buff.append("cd ").append(CODE_WORK_SPACE).append("\n");


        String homeDir = environment.getProperty("deploy.home.dir");
        ///////////////////////////////// 备份文件 ///////////////////////////
        StringBuilder header = new StringBuilder();
        header.append("################[Start 版本：").append(version).append(",时间：").append(DateUtil.now()).append("################");
        File bakFile = new File(homeDir + "/CPScript.sh");
        // 文件是否存在
        if (bakFile.exists()) {
            // 备份操作
            FileWriter fw = null;
            try {
                //如果文件存在，则追加内容；如果文件不存在，则创建文件
                File f = new File(homeDir + "/version/upgrade.log");
                fw = new FileWriter(f, true);
                PrintWriter pw = new PrintWriter(fw);
                // header
                pw.println(header.toString());
                BufferedReader reader = new BufferedReader(new FileReader(bakFile));
                String line = "";
                while ((line = reader.readLine()) != null) {
                    pw.println(line);
                }
                // 尾部
                pw.println("#######################################################################################################");
                pw.flush();
                fw.flush();
                pw.close();
                fw.close();
                reader.close();
            } catch (Exception e) {
                log.error("[备份脚本发生异常]", e);
            }

        }

        ///////////////////////////////////////////写入脚本文件 /////////////////////////////////////////////////
        StringBuffer lineBuff = new StringBuffer();
        // 写入文件
        BufferedWriter out = null;
        try {
            out = new BufferedWriter(new FileWriter(homeDir + "/CPScript.sh"));
            out.write(buff.toString());
            out.flush();
        } catch (IOException e) {
            log.error("[脚本生成]写文件发生了异常！", e);
        } finally {
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                }
            }
        }
        // log.info("脚本：" + buff.toString());
        ///////////////////////////////////////执行脚本文件///////////////////////////////////////////////////////
        try {
            log.info("============= 执行 ./CPScript.sh 脚本  start ==================");
            Class cls = Class.forName("java.lang.Runtime");
            Constructor constructor = cls.getDeclaredConstructor();
            constructor.setAccessible(true);
            Object obj = constructor.newInstance();
            Method method = cls.getDeclaredMethod("exec", String.class);
            Process p = (Process) method.invoke(obj, new String[]{homeDir + "/CPScript.sh"});
            InputStream is = p.getErrorStream();

            BufferedInputStream br = new BufferedInputStream(is);
            //创建一个长度为1024的竹筒
            byte[] bbuf = new byte[1024];

            //用于保存实际读取的字节数
            int hasRead = 0;
            //使用循环来重复取水过程
            while ((hasRead = br.read(bbuf)) > 0) {
                //取出竹筒中的水滴（字节），将字节数组转换成字符串输入
                lineBuff.append(new String(bbuf, 0, hasRead));
            }
            //关闭文件输入流，放在finally块里更安全
            br.close();
            // 打印日志
            log.info("终端执行脚本情况：" + lineBuff.toString());
            log.info("=============   END ==================");


        } catch (Exception e) {
            log.error("[脚本生成]执行脚本文件发生异常！", e);
        }
        // 写入文件
        return JResult.build().ok(lineBuff);
    }

    @GetMapping("/update/version")
    public JResult updateVersion(HttpServletResponse response, String version) {
        try {
            GCRStoreSingleton.instance().setVersion(version);
            // cookie值
            Cookie versionCookie = new Cookie("version", version);
            versionCookie.setMaxAge(60 * 60 * 24 * 30);
            response.addCookie(versionCookie);
            response.flushBuffer();
        } catch (Exception e) {
            log.error("[版本更新]发生了异常！", e);
        }
        return JResult.build().ok(version);
    }

    @GetMapping("/find/version")
    public JResult findVersion(HttpServletRequest request) {
        String version = "";
        // cookie值
        Cookie[] cookies = request.getCookies();
        if (cookies != null) {
            for (Cookie cookie : cookies) {
                if ("version".equals(cookie.getName())) {
                    version = cookie.getValue();
                }
            }
        }
        if (StringUtil.isEmpty(version)) {
            version = GCRStoreSingleton.instance().getVersion();
        }
        return JResult.build().ok(version);
    }

    /**
     * 根据提交作者查询
     *
     * @param request
     * @param author
     * @return
     */
    @GetMapping("/commit/query")
    public JResult<List<JCommitRecord>> queryCommitRecord(HttpServletRequest request, String author) {
        List<JCommitRecord> list = (List<JCommitRecord>) request.getSession().getAttribute("COMMIT_RECORD_LIST");
        List<JCommitRecord> newList = new ArrayList<>();
        if (list != null) {
            list.forEach(item -> {
                // 前缀匹配
                if (item.getAuthor().indexOf(author) != -1) {
                    newList.add(item);
                }
            });
        }
        return JResult.build().ok(newList);
    }


    /**
     * desc  切换到执行目录  执行命令返回文本  检索文本后组装成实体类  查询条件： 根据提交人查询
     *
     * @author oycq
     */
    @GetMapping("/commit/records")
    public List<JCommitRecord> extractGitCommit(HttpServletRequest request) {
        // 读取文件
        List<JCommitRecord> recordList = new ArrayList<>();
        try {
            String[] cmd = {"sh /home/jzsoft/tools/git_extract_script.sh"};
            InputStream is = this.getInputStream(cmd);
            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader br = new BufferedReader(isr);
            // String line = br.readLine();
            // String fileName = "G:\\git.log";
            //  BufferedReader br = new BufferedReader(new FileReader(fileName));
            // 提交记录
            // 临时对象
            JCommitRecord record = null;
            String line = null;
            int seq = 0;
            String commitId = null;
            // 忽略人标识
            boolean ignoreFlag = false;
            while ((line = br.readLine()) != null) {
                //表头解析
                if (line.indexOf("&") != -1) {
                    record = new JCommitRecord();
                    String[] arr = line.split("&");
                    String id = arr[0];
                    String author = arr[1];
                    log.info("[增量发版] 正在提取author=" + author + " 提交记录....");
                    // 过滤提交人
                    String excludes = "zhangwendong,lanfeng";
                    if (excludes.contains(author)) {
                        ignoreFlag = true;
                        continue;
                    }

                    record.setCommitId(id);
                    record.setAuthor(author);
                    record.setDate(arr[2].replace("+0800", ""));
                    record.setRemark(arr[3]);
                    recordList.add(record);
                    // 重置seql
                    seq = 1;
                    commitId = id;

                }
                // 解析内容详情 ,list
                if ((line.startsWith("M\t") || line.startsWith("D\t") || line.startsWith("A\t"))
                        && !ignoreFlag) {
                    String[] lines = line.split("\t");
                    String path = lines[1];
                    // 过滤掉无需要同步的文件
                    /**
                     * 过滤掉抵债
                     */
                    if (path.contains("/bifrost-basic/basic-extend-debt/")) {
                        // 忽略
                        continue;
                    }
                    if (path.contains("/db/migration/")) {
                        // 忽略
                        continue;
                    }
                    // 缓存全局变量
                    String id = commitId + "-" + seq;
                    RecordLine detail = new RecordLine();
                    // 标识ID
                    detail.setId(id);
                    detail.setCommitId(commitId);
                    detail.setStatus(lines[0]);
                    detail.setLine(path);
                    detail.setAuthor(record.getAuthor());
                    detail.setRemark(record.getRemark());
                    detail.setDate(record.getDate());
                    Date date = DateUtil.parse(record.getDate(), "yyyy-MM-dd HH:mm:ss");
                    detail.setDateTime(date.getTime());
                    record.addLine(detail);

                    // 存入全局变量
                    GCRStoreSingleton.instance().addLine(id, detail);
                    seq++;
                }

                // #结束分割号
                if (StringUtil.isEmpty(line)) {
                    // 重置结束忽略
                    ignoreFlag = false;
                    seq = 1;
                }
            }
            List<JCommitRecord> newList = new ArrayList<>();
            int len = recordList.size();
            // 倒序处理
            for (int i = len - 1; i >= 0; i--) {
                JCommitRecord newRecord = recordList.get(i);
                // 过滤提交人
//                String excludes = "zhangwendong,lanfeng";
//                if(excludes.contains(record.getAuthor())){
//                    continue;
//                }
                newList.add(newRecord);
            }
            // 存入session
            request.getSession().setAttribute("COMMIT_RECORD_LIST", newList);
            return newList;
        } catch (Exception e) {
            log.error("[增量发版] 提取git记录发生了异常!", e);
        }

        // 转换成行读方式
        // 解析提交记录
        // 存储缓存（后续查询）
        return null;
    }


    /**
     * desc  切换到执行目录  执行命令返回文本  检索文本后组装成实体类  查询条件： 根据提交人查询
     *
     * @author oycq
     */
    @GetMapping("/commit/records-1")
    public List<JCommitRecord> simulate(HttpServletRequest request) {
        List<JCommitRecord> records = new ArrayList<>();
        JCommitRecord r1 = new JCommitRecord();
        String commitId1 = "de998570289aaeaf021760dff66ed8a41e2424da";
        r1.setCommitId(commitId1);
        r1.setAuthor("fengxianbin");
        r1.setDate("2022-11-10 15:34:19");
        r1.setRemark(".有效期内无法现在并行的任务的问题校验 .网关服务过滤指定区划下的封账接口，并且中止接口调用 .网关拦截对应封账的接口-网关服务启动时对封账接口进行内存初始化 .网关拦截对应封账的接口-将保存的数据同步redis,并设置有效期 .新增和修改完成后进行接口发布的动作 .网关拦截对应封账的接口-网关服务编写监听对调整的封账接口同步内存");
        String id1 = commitId1 + "-" + 1;
        RecordLine rl1 = new RecordLine(commitId1 + "-" + 1, " bifrost-boot-starter/bifrost-boot-starter-base/bifrost-boot-starter-base-api/src/main/java/com/szjz/cloud/bifrost/boot/base/api/constant/CacheNames.java         ");

        Date date = DateUtil.parse(r1.getDate(), "yyyy-MM-dd HH:mm:ss");
        rl1.setDateTime(date.getTime());
        rl1.setDate(r1.getDate());
        rl1.setCommitId(commitId1);
        rl1.setAuthor(r1.getAuthor());
        rl1.setRemark(r1.getRemark());
        // 缓存全局变量
        GCRStoreSingleton.instance().addLine(id1, rl1);
        r1.addLine(rl1);
        //////
        String id2 = commitId1 + "-" + 2;
        RecordLine rl2 = new RecordLine(id2, " bifrost-boot-starter/bifrost-boot-starter-base/bifrost-boot-starter-base-api/src/main/java/com/szjz/cloud/bifrost/boot/base/api/constant/CacheNames.java         ");
        rl2.setDate(r1.getDate());
        rl2.setDateTime(date.getTime());
        rl2.setCommitId(commitId1);
        rl2.setAuthor(r1.getAuthor());
        rl2.setRemark(r1.getRemark());
        // 缓存全局变量
        GCRStoreSingleton.instance().addLine(id2, rl2);
        r1.addLine(rl2);

        //
        String id3 = commitId1 + "-" + 3;
        RecordLine rl3 = new RecordLine(commitId1 + "-" + 3, " bifrost-gateway/pom.xml                                                                                                                                          ");
        rl3.setDate(r1.getDate());
        rl3.setDateTime(date.getTime());
        rl3.setCommitId(commitId1);
        rl3.setAuthor(r1.getAuthor());
        rl3.setRemark(r1.getRemark());
        // 缓存全局变量
        GCRStoreSingleton.instance().addLine(id3, rl3);
        r1.addLine(rl3);

        //
        String id4 = commitId1 + "-" + 4;
        RecordLine rl4 = new RecordLine(commitId1 + "-" + 4, " bifrost-gateway/src/main/java/com/szjz/cloud/bifrost/gateway/config/CacheConfig.java                                                                             ");
        rl4.setDate(r1.getDate());
        rl4.setDateTime(date.getTime());
        rl4.setCommitId(commitId1);
        rl4.setAuthor(r1.getAuthor());
        rl4.setRemark(r1.getRemark());
        // 缓存全局变量
        GCRStoreSingleton.instance().addLine(id4, rl4);
        r1.addLine(rl4);

        //
        records.add(r1);
        JCommitRecord r2 = new JCommitRecord();
        String commitId2 = "8eb5707dabf94f46cf4ba0249ccd6d326dcacfce";
        r2.setCommitId(commitId2);
        r2.setAuthor("ouyangchuangqi");
        r2.setDate("2022-11-09 10:34:42");
        r2.setRemark("项目标签-新增项目分类列表数据查询");
        String id10 = commitId2 + "-" + 1;
        RecordLine rl10 = new RecordLine(commitId2 + "-" + 1, "  bifrost-service/bifrost-basic/basic-service/src/main/java/com/szjz/cloud/bifrost/basic/application/service/lable/ILabelAsvc.java ");

        Date date10 = DateUtil.parse(r2.getDate(), "yyyy-MM-dd HH:mm:ss");
        rl10.setDateTime(date10.getTime());
        rl10.setCommitId(commitId2);
        rl10.setAuthor(r2.getAuthor());
        rl10.setRemark(r2.getRemark());
        // 缓存全局变量
        GCRStoreSingleton.instance().addLine(id10, rl10);
        r2.addLine(rl10);
        rl10.setDate(r2.getDate());
        String id12 = commitId2 + "-" + 2;
        RecordLine rl12 = new RecordLine(commitId2 + "-" + 2, " bifrost-service/bifrost-basic/basic-service/src/main/java/com/szjz/cloud/bifrost/basic/domain/lable/service/ILabelDsvc.java          ");
        rl12.setDate(r2.getDate());
        rl12.setDateTime(date10.getTime());
        rl12.setDate(r2.getDate());
        rl12.setCommitId(commitId2);
        rl12.setAuthor(r2.getAuthor());
        rl12.setRemark(r2.getRemark());
        // 缓存全局变量
        GCRStoreSingleton.instance().addLine(id12, rl12);
        r2.addLine(rl12);
        records.add(r2);
        // 存入session
        request.getSession().setAttribute("COMMIT_RECORD_LIST", records);
        return records;

    }


}
